package com.sinn.gitrepobranchcompare.tool;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.stream.Stream;

public class Tool {

    /**
     * 判断 path 文件夹是否存在，以及是否为文件夹
     *      文件夹不存在，则创建；
     *          创建成功返回 true
     *          创建失败返回 false
     *      文件夹存在，则判断是否为文件夹：
     *          如果是文件夹，返回 true
     *          不是文件夹，返回 false
     * @param path 文件夹路径
     * @return 校验结果
     */
    public static boolean checkAndBuildFilePath(String path) {
        File checkDir = new File(path);
        if (!checkDir.exists()) {
            boolean result = checkDir.mkdir();
            if (!result) {
                System.out.println("创建目录失败，目录为" + checkDir.getAbsolutePath());
                return false;
            }
        }

        if (!checkDir.isDirectory()) {
            System.out.println("当前路径不是目录，" + path);
            return false;
        }

        return true;
    }

    public static void moveGitIndexFile(String srcDir, String destDir) {
        try {
            Path srcPath = Paths.get(srcDir);
            Path destPath = Paths.get(destDir);

            // 遍历源目录下的所有文件和文件夹
            try (Stream<Path> stream = Files.walk(srcPath)) {
                stream.forEach(path -> {
                    try {
                        // 计算目标路径，不保留原目录结构
//                        Path dest = destPath.resolve(srcPath.relativize(path));
                        // 保留原目录结构
                        Path dest = destPath.resolve(srcPath.getFileName()).resolve(srcPath.relativize(path));
                        // 如果目标路径已存在，则替换
                        if (Files.exists(dest)) {
                            Files.delete(dest); // 删除已存在的文件或目录
                        }

                        Files.createDirectories(dest.getParent());

                        // 移动文件或目录
                        Files.copy(path, dest, StandardCopyOption.REPLACE_EXISTING);
//                        System.out.println("移动成功: " + path + " -> " + dest);
                    } catch (IOException e) {
                        System.err.println("移动失败: " + path + " -> " + destPath);
                        e.printStackTrace();
                    }
                });
            }
            deleteFileOrDirectory(srcPath);
        } catch (IOException e) {
            System.err.println("移动文件失败, 源目录：" + srcDir + ", 目标目录：" + destDir);
            e.printStackTrace();
        }
    }

    public static void copyGitIndexFile(String srcDir, String destDir) {
        copyGitIndexFile(new File(srcDir), new File(destDir));
    }

    public static void copyGitIndexFile(File src, File dest) {
        if (!dest.exists()) {
            dest.mkdir();
        }

        File[] srcFiles = src.listFiles();
        if (srcFiles != null) {
            for (File file: srcFiles) {
                String fileName = file.getName();
                if (file.isDirectory()) {
                    File newDir = new File(dest, fileName);
                    copyGitIndexFile(file, newDir);
                } else {
                    try {
                        Files.copy(file.toPath(), Paths.get(dest.getAbsolutePath(), fileName), StandardCopyOption.REPLACE_EXISTING);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    public static void appendToFile(String filePath, StringBuilder content) {
        try {
            filePath = filePath.replaceAll("\"", "");
            // 统一路径分隔符
            Path path = Paths.get(filePath);

            // 递归创建父目录
            Path parentDir = path.getParent();
            if (parentDir != null) {
                Files.createDirectories(parentDir);
            }

            // 创建文件
            if (!Files.exists(path)) {
                Files.createFile(path);
//                System.out.println("文件创建成功: " + path.toAbsolutePath());
            }



            File file = new File(filePath);

            FileOutputStream fos = new FileOutputStream(file, true);
            OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8);
            BufferedWriter writer = new BufferedWriter(osw);
            writer.write(content.toString());
            writer.flush();
            writer.close();
            osw.close();
            fos.close();
        } catch (Exception e) {
            System.out.println("current file info:" + filePath);
            e.printStackTrace();
        }
    }

    public static void deleteFileOrDirectory(String srcPath) {
        Path path = Paths.get(srcPath);
        deleteFileOrDirectory(path);
    }

    public static void deleteFileOrDirectory(Path path) {
        if (Files.exists(path)) {
            try {
                // 如果是目录，递归删除其内容
                if (Files.isDirectory(path)) {
                    try (DirectoryStream<Path> stream = Files.newDirectoryStream(path)) {
                        for (Path entry : stream) {
                            deleteFileOrDirectory(entry); // 递归删除子文件或子目录
                        }
                    }
                }

                // 设置文件为可写（如果是只读文件）
                if (Files.isRegularFile(path)) {
                    Files.setAttribute(path, "dos:readonly", false);
                }

                // 删除文件或空目录
                int retryCount = 3;
                while (retryCount > 0) {
                    try {
                        Files.delete(path);
//                        System.out.println("删除成功: " + path);
                        break; // 成功则退出重试
                    } catch (AccessDeniedException e) {
                        retryCount--;
                        if (retryCount == 0) {
                            System.err.println("权限不足，跳过文件: " + path);
                        } else {
                            System.err.println("权限不足，正在重试 (" + retryCount + " 次剩余): " + path);
                            Thread.sleep(1000); // 等待 1 秒后重试
                        }
                    } catch (IOException e) {
                        retryCount--;
                        if (retryCount == 0) {
                            System.err.println("删除失败（重试次数用尽）: " + path);
                            e.printStackTrace();
                        } else {
                            System.err.println("删除失败，正在重试 (" + retryCount + " 次剩余): " + path);
                            Thread.sleep(1000); // 等待 1 秒后重试
                        }
                    }
                }
            } catch (IOException | InterruptedException e) {
                System.err.println("操作失败: " + path);
                e.printStackTrace();
            }
        } else {
            System.out.println("文件或目录不存在: " + path);
        }
    }

    /**
     * 根据文件名生成 SHA-256 哈希值
     *
     * @param fileName 文件名
     * @return SHA-256 哈希值（十六进制字符串）
     */
    public static String generateSHA256(String fileName) {
        try {
            // 创建 MessageDigest 实例，指定算法为 SHA-256
            MessageDigest digest = MessageDigest.getInstance("SHA-256");

            // 将文件名转换为字节数组
            byte[] hashBytes = digest.digest(fileName.getBytes(StandardCharsets.UTF_8));

            // 将字节数组转换为十六进制字符串
            StringBuilder hexString = new StringBuilder();
            for (byte b : hashBytes) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) {
                    hexString.append('0'); // 补齐前导零
                }
                hexString.append(hex);
            }

            return hexString.toString();
        } catch (NoSuchAlgorithmException e) {
            // SHA-256 算法不可用时抛出异常
            throw new RuntimeException("SHA-256 算法不可用", e);
        }
    }

}
